home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pine / context.c < prev    next >
C/C++ Source or Header  |  1996-03-14  |  23KB  |  830 lines

  1. #if !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: context.c,v 4.48 1996/03/15 07:13:42 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Mailbox Context Management
  6.  *
  7.  * Author:    Mark Crispin
  8.  *        Networks and Distributed Computing
  9.  *        Computing & Communications
  10.  *        University of Washington
  11.  *        Administration Building, AG-44
  12.  *        Seattle, WA  98195
  13.  *        Internet: MRC@CAC.Washington.EDU
  14.  *
  15.  *
  16.  * Pine and Pico are registered trademarks of the University of Washington.
  17.  * No commercial use of these trademarks may be made without prior written
  18.  * permission of the University of Washington.
  19.  *
  20.  * Pine, Pico, and Pilot software and its included text are Copyright
  21.  * 1989-1996 by the University of Washington.
  22.  *
  23.  * The full text of our legal notices is contained in the file called
  24.  * CPYRIGHT, included with this distribution.
  25.  *
  26.  *
  27.  * USENET News reading additions in part by L Lundblade / NorthWestNet, 1993
  28.  * lgl@nwnet.net
  29.  */
  30.  
  31. #include "headers.h"
  32.  
  33. char *current_context = NIL;    /* current context for FIND */
  34.  
  35. /* Mailbox found
  36.  * Accepts: Mailbox name as FQN
  37.  */
  38.  
  39. void
  40. mm_mailbox (string)
  41.     char *string;
  42. {
  43.     context_fqn_to_an (context_mailbox,current_context,string);
  44. }
  45.  
  46.  
  47. /* BBoard found
  48.  * Accepts: BBoard name as FQN
  49.  */
  50.  
  51. void
  52. mm_bboard (string)
  53.     char *string;
  54. {
  55.     context_fqn_to_an (context_bboard,current_context,string);
  56. }
  57.  
  58. /* Convert fully-qualified name to ambiguous name and send to function
  59.  * Accepts: find return function
  60.  *        current context
  61.  *        fully-qualified name
  62.  */
  63.  
  64. void
  65. context_fqn_to_an (f, context_string, fqn)
  66.     find_return f;
  67.     char *context_string,*fqn;
  68. {
  69.   char tmp[MAILTMPLEN];
  70.   char *ret = fqn;
  71.   char *delimiter,*prefix,*suffix;
  72.   int pfxlen = 0;
  73.   int sfxlen = 0;
  74.   int fqnlen = strlen (fqn);
  75.   int anlen;
  76.   char context[MAILTMPLEN];
  77.  
  78.   if (context_string && *context_string && /* have a valid context? */
  79.       context_digest(context_string, context, NULL, NULL, NULL) == NULL){
  80.     delimiter = strstr(context, "%s");
  81.                 /* determine prefix */
  82.     pfxlen = delimiter - context;
  83.     if (pfxlen) {
  84.       strncpy (tmp,context,pfxlen);
  85.       prefix = tmp;
  86.       prefix[pfxlen] = '\0';
  87.     } else
  88.       prefix = NIL;
  89.                 /* determine suffix */
  90.     if (suffix = delimiter[2] ? delimiter+2 : NIL) sfxlen = strlen (suffix);
  91.  
  92.     /*
  93.      * The fqn prefix may not match the context prefix.
  94.      * Two cases so far:
  95.      *   1) mail_find on open stream returns {host}context
  96.      *   2) mail_find_all returns full paths though find string
  97.      *      relative
  98.      */
  99.  
  100.     if((ret=((!prefix) ? fqn : strstr(fqn, prefix))) != NULL){
  101.     if(prefix && !strcmp(fqn = ret, prefix))
  102.       return;            /* no folder name! */
  103.  
  104.     fqnlen = strlen(fqn);
  105.     }
  106.  
  107.     /* Determine if FQN is proper match for given prefix and suffix.  This
  108.      * should normally always happen, but if it doesn't, it probably means
  109.      * that this test isn't hairy enough and needs more work.
  110.      */
  111.     if (((anlen = fqnlen - (pfxlen + sfxlen)) < 1) ||
  112.     (pfxlen && strncmp (prefix,fqn,pfxlen) != 0) ||
  113.     (sfxlen && strcmp (suffix,fqn + fqnlen - sfxlen) != 0)) {
  114.       sprintf (tmp,"Found mailbox outside context: %s",fqn);
  115.       mm_log (tmp,(long) NIL);
  116.       pfxlen = 0;
  117.       anlen  = fqnlen;
  118.     }
  119.                 /* copy the an */
  120.     strcpy (ret = tmp,fqn+pfxlen);
  121.     ret[anlen] = '\0';        /* tie off string */
  122.   }
  123.   (*f) (ret);            /* in case no context? */
  124. }
  125.  
  126.  
  127. /* Context Manager context format digester
  128.  * Accepts: context string and buffers for sprintf-suitable context,
  129.  *          remote host (for display), remote context (for display), 
  130.  *          and view string
  131.  * Returns: NULL if successful, else error string
  132.  *
  133.  * Comments: OK, here's what we expect a fully qualified context to 
  134.  *           look like:
  135.  *
  136.  * [*] [{host ["/"<proto>] [:port]}] [<cntxt>] "[" [<view>] "]" [<cntxt>]
  137.  *
  138.  *         2) It's understood that double "[" or "]" are used to 
  139.  *            quote a literal '[' or ']' in a context name.
  140.  *
  141.  *         3) an empty view in context implies a view of '*', so that's 
  142.  *            what get's put in the view string
  143.  *
  144.  */
  145. char *
  146. context_digest (context, scontext, host, rcontext, view)
  147.     char *context, *scontext, *host, *rcontext, *view;
  148. {
  149.     char *p, *viewp = view, tmp[MAILTMPLEN];
  150.     int   i = 0;
  151.  
  152.     if((p = context) == NULL || *p == '\0'){
  153.     if(scontext)            /* so the caller can apply */
  154.       strcpy(scontext, "%s");    /* folder names as is.     */
  155.  
  156.     return(NULL);            /* no error, just empty context */
  157.     }
  158.  
  159.     if(!rcontext && scontext)        /* place to collect rcontext ? */
  160.       rcontext = tmp;
  161.  
  162.     /* find hostname if requested and exists */
  163.     if(*p == '{' || (*p == '*' && *++p == '{')){
  164.     for(p++; *p && *p != '/' && *p != ':' && *p != '}' ; p++)
  165.       if(host)
  166.         *host++ = *p;        /* copy host if requested */
  167.  
  168.     while(*p && *p != '}')        /* find end of imap host */
  169.       p++;
  170.  
  171.     if(*p == '\0')
  172.       return("Unbalanced '}'");    /* bogus. */
  173.     else
  174.       p++;                /* move into next field */
  175.     }
  176.  
  177.     for(; *p ; p++){            /* get thru context */
  178.     if(rcontext)
  179.       rcontext[i++] = *p;        /* copy if requested */
  180.  
  181.     if(*p == '['){            /* done? */
  182.         if(*++p == '\0')        /* look ahead */
  183.           return("Unbalanced '['");
  184.  
  185.         if(*p != '[')        /* not quoted: "[[" */
  186.           break;
  187.     }
  188.     }
  189.  
  190.     if(*p == '\0')
  191.       return("No '[' in context");
  192.  
  193.     for(; *p ; p++){            /* possibly in view portion ? */
  194.     if(*p == ']'){
  195.         if(*(p+1) == ']')        /* is quoted */
  196.           p++;
  197.         else
  198.           break;
  199.     }
  200.  
  201.     if(viewp)
  202.       *viewp++ = *p;
  203.     }
  204.  
  205.     if(*p != ']')
  206.       return("No ']' in context");
  207.  
  208.     for(; *p ; p++){            /* trailing context ? */
  209.     if(rcontext)
  210.       rcontext[i++] = *p;
  211.     }
  212.  
  213.     if(host) *host = '\0';
  214.     if(rcontext) rcontext[i] = '\0';
  215.     if(viewp) {
  216.     if(viewp == view)
  217.       *viewp++ = '*';
  218.  
  219.     *viewp = '\0';
  220.     }
  221.  
  222.     if(scontext){            /* sprint'able context request ? */
  223.     if(*context == '*')
  224.       *scontext++ = *context++;
  225.  
  226.     if(*context == '{'){
  227.         while(*context && *context != '}')
  228.           *scontext++ = *context++;
  229.  
  230.         *scontext++ = '}';
  231.     }
  232.  
  233.     for(p = rcontext; *p ; p++){
  234.         if(*p == '[' && *(p+1) == ']'){
  235.         *scontext++ = '%';    /* replace "[]" with "%s" */
  236.         *scontext++ = 's';
  237.         p++;            /* skip ']' */
  238.         }
  239.         else
  240.           *scontext++ = *p;
  241.     }
  242.  
  243.     *scontext = '\0';
  244.     }
  245.  
  246.     return(NULL);            /* no problems to report... */
  247. }
  248.  
  249.  
  250. /* Context Manager apply name to context
  251.  * Accepts: buffer to write, context to apply, ambiguous folder name
  252.  * Returns: buffer filled with fully qualified name in context
  253.  *          No context applied if error
  254.  */
  255. void
  256. context_apply(b, c, n)
  257.     char *b, *c, *n;
  258. {
  259.     char tmp[MAILTMPLEN];
  260.  
  261.     if(context_digest(c, tmp, NULL, NULL, NULL) == NULL)
  262.       sprintf(b, tmp, n);        /* everythings ok,  */
  263.     else
  264.       strcpy(b, n);            /* don't apply bogus context */
  265. }
  266.  
  267.  
  268. /* Context Manager check if name is ambiguous
  269.  * Accepts: candidate string
  270.  * Returns: T if ambiguous, NIL if fully-qualified
  271.  */
  272.  
  273. int
  274. context_isambig (s)
  275.     char *s;
  276. {
  277.                 /* first character after possible bboard * */
  278.     char c = (*s == '*') ? *(s+1) : *s;
  279.     if(c == '\0' && *s == '*')    /* special case! */
  280.       return(1);
  281. #if defined(DOS) || defined(OS2)
  282.     else if (c != '{' && isalpha(*s) && *(s+1) == ':')
  283.       return(0);
  284. #endif
  285.     else
  286.       /*
  287.        * Since we can't know how the server handles foldernames or
  288.        * heirarchy, treat only what we know as being absolute folder
  289.        * specifiers.  We know '{' means a c-client remote folder, and
  290.        * that '/' breaks out of the current context under UNIX, and we're
  291.        * guessing that '[' and ':' are special under VMS (for which
  292.        * a couple of imapd's are known).  If you know this guess to be
  293.        * wrong or know of other servers, please send us diffs for this...
  294.        * 
  295.        * The good news is, THIS MUST AND WILL BE REMOVED
  296.        * WITH THE COMING IMAP4 SUPPORT!!!!
  297.        */
  298.       return(!(c == '{' || c == '/' || c == ':' || c == '[' || c == '#'
  299.            || strucmp(s, ps_global->inbox_name) == 0));
  300. }
  301.  
  302. /* Context Manager find list of subscribed mailboxes
  303.  * Accepts: context
  304.  *        mail stream
  305.  *        pattern to search
  306.  */
  307.  
  308. void
  309. context_find (context, stream, pat)
  310.     char       *context;
  311.     MAILSTREAM *stream;char *pat;
  312. {
  313.   char tmp[MAILTMPLEN];
  314.                 /* must be within context */
  315.   if (!context_isambig (pat)) {
  316.     sprintf (tmp,"Find of mailbox outside context: %s",pat);
  317.     mm_log (tmp,(long) NIL);
  318.     strcpy(tmp, pat);        /* allow find for now */
  319.   }
  320.   else{
  321.     current_context = context;    /* note current context */
  322.     context_apply (tmp,context,pat); /* build fully-qualified name */
  323.   }
  324.  
  325.   mail_find (stream,tmp);/* try to do the find */
  326. }
  327.  
  328.  
  329. /* Context Manager find list of subscribed bboards
  330.  * Accepts: context
  331.  *        mail stream
  332.  *        pattern to search
  333.  */
  334.  
  335. void
  336. context_find_bboards (context, stream, pat)
  337.     char       *context;
  338.     MAILSTREAM *stream;
  339.     char       *pat;
  340. {
  341.   char tmp[MAILTMPLEN];
  342.                 /* must be within context */
  343.   if (!context_isambig (pat)) {
  344.     sprintf (tmp,"Find of bboard outside context: %s",pat);
  345.     mm_log (tmp,(long) NIL);
  346.     strcpy(tmp, pat);        /* allow find for now */
  347.   }
  348.   else{
  349.     current_context = context;    /* note current context */
  350.     context_apply (tmp,context,pat); /* build fully-qualified name */
  351.   }
  352.  
  353.   mail_find_bboards (stream,tmp);
  354. }
  355.  
  356. /* Context Manager find list of all mailboxes
  357.  * Accepts: context
  358.  *        mail stream
  359.  *        pattern to search
  360.  */
  361.  
  362. void
  363. context_find_all (context, stream, pat)
  364.     char       *context;
  365.     MAILSTREAM *stream;
  366.     char       *pat;
  367. {
  368.   char tmp[MAILTMPLEN];
  369.                 /* must be within context */
  370.   if (!context_isambig (pat)) {
  371.     sprintf (tmp,"Find of mailbox outside context: %s",pat);
  372.     mm_log (tmp,(long) NIL);
  373.     strcpy(tmp, pat);        /* allow find for now */
  374.   }
  375.   else{
  376.     current_context = context;    /* note current context */
  377.     context_apply (tmp,context,pat); /* build fully-qualified name */
  378.   }
  379.                 /* try to do the find */
  380.   mail_find_all (stream,tmp);
  381. }
  382.  
  383.  
  384. /* Context Manager find list of all bboards
  385.  * Accepts: context
  386.  *        mail stream
  387.  *        pattern to search
  388.  */
  389.  
  390. void
  391. context_find_all_bboard (context, stream, pat)
  392.     char       *context;
  393.     MAILSTREAM *stream;
  394.     char       *pat;
  395. {
  396.   char tmp[MAILTMPLEN];
  397.                 /* must be within context */
  398.   if (!context_isambig (pat)) {
  399.     sprintf (tmp,"Find of bboard outside context: %s",pat);
  400.     mm_log (tmp,(long) NIL);
  401.     strcpy(tmp, pat);        /* allow find for now */
  402.   }
  403.   else{
  404.     current_context = context;    /* note current context */
  405.     context_apply (tmp,context,pat); /* build fully-qualified name */
  406.   }
  407.                 /* try to do the find */
  408.   mail_find_all_bboard (stream,tmp);
  409. }
  410. #ifdef NEWBB
  411. /* Context Manager find list of new bboards
  412.  * Accepts: context
  413.  *        mail stream
  414.  *        pattern to search
  415.  */
  416.  
  417. void
  418. context_find_new_bboard (context, stream, pat, lasttime)
  419.     char       *context;
  420.     MAILSTREAM *stream;
  421.     char       *pat, *lasttime;
  422. {
  423.   char tmp[MAILTMPLEN];
  424.                 /* must be within context */
  425.   if (!context_isambig (pat)) {
  426.     sprintf (tmp,"Find of bboard outside context: %s",pat);
  427.     mm_log (tmp,WARN);
  428.     strcpy(tmp, pat);        /* allow find for now */
  429.   }
  430.   else{
  431.     current_context = context;    /* note current context */
  432.     context_apply (tmp,context,pat); /* build fully-qualified name */
  433.   }
  434.                 /* try to do the find */
  435.   nntp_find_new_bboard (stream,tmp, lasttime);
  436. }
  437.  
  438. #endif
  439.  
  440. /* Context Manager create mailbox
  441.  * Accepts: context
  442.  *        mail stream
  443.  *        mailbox name to create
  444.  * Returns: T on success, NIL on failure
  445.  */
  446.  
  447. long
  448. context_create (context, stream, mailbox)
  449.     char       *context;
  450.     MAILSTREAM *stream;
  451.     char       *mailbox;
  452. {
  453.   char tmp[MAILTMPLEN];        /* must be within context */
  454.  
  455.   if (!context_isambig (mailbox)) {
  456.     char *s, errbuf[MAILTMPLEN];
  457.     if(mailbox[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  458.       strncpy(tmp, context, (s - context) + 1);
  459.       strcpy(&tmp[(s - context)+1], mailbox);
  460.     }
  461.     else strcpy(tmp, mailbox);    /* allow create for now */
  462.  
  463.     sprintf (errbuf,"Create of mailbox outside context: %s", tmp);
  464.     mm_log (errbuf,(long) NIL);
  465.   }
  466.   else
  467.     context_apply (tmp,context,mailbox);/* build fully-qualified name */
  468.                 /* try to do the create */
  469.   return(cntxt_allowed(tmp) ? mail_create(stream,tmp) : 0L);
  470. }
  471.  
  472.  
  473. /* Context Manager open
  474.  * Accepts: context
  475.  *        candidate stream for recycling
  476.  *        mailbox name
  477.  *        open options
  478.  * Returns: stream to use on success, NIL on failure
  479.  */
  480.  
  481. MAILSTREAM *
  482. context_open (context, old, name, opt)
  483.     char       *context;
  484.     MAILSTREAM *old;
  485.     char       *name;
  486.     long    opt;
  487. {
  488.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  489.   char host[MAILTMPLEN];
  490.  
  491.   if (!context) context = "[]";    /* non spec'd, pass name */
  492.   if(context_isambig (name)) context_apply(s = tmp, context, name);
  493.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  494.       strncpy(tmp, context, (s - context) + 1);
  495.       strcpy(&tmp[(s - context)+1], name);
  496.       s = tmp;
  497.   }
  498.   else s = name;        /* fully-qualified name */
  499.   return(cntxt_allowed(s) ? mail_open(old,s,opt) : (MAILSTREAM *)NULL);
  500. }
  501.  
  502.  
  503. /* Context Manager rename
  504.  * Accepts: context
  505.  *        mail stream
  506.  *        old mailbox name
  507.  *        new mailbox name
  508.  * Returns: T on success, NIL on failure
  509.  */
  510.  
  511. long
  512. context_rename (context, stream, old, new)
  513.     char       *context;
  514.     MAILSTREAM *stream;
  515.     char       *old, *new;
  516. {
  517.   char *s,*t,tmp[MAILTMPLEN],tmp2[MAILTMPLEN];
  518.     /* build FQN from ambiguous name */
  519.   if (context_isambig (old)) context_apply (s = tmp,context,old);
  520.   else if(old[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  521.       strncpy(tmp, context, (s - context) + 1);
  522.       strcpy(&tmp[(s - context)+1], old);
  523.       s = tmp;
  524.   }
  525.   else s = old;        /* fully-qualified name */
  526.   if (context_isambig (new)) context_apply (t = tmp2,context,new);
  527.   else if(new[0] != '{' && context[0] == '{' && (t = strindex(context, '}'))){
  528.       strncpy(tmp, context, (t - context) + 1);
  529.       strcpy(&tmp[(t - context)+1], new);
  530.       t = tmp;
  531.   }
  532.   else t = new;        /* fully-qualified name */
  533.   return((cntxt_allowed(s) && cntxt_allowed(t)) ? mail_rename(stream,s,t)
  534.                          : 0L);
  535. }
  536.  
  537.  
  538. /* Context Manager delete mailbox
  539.  * Accepts: context
  540.  *        mail stream
  541.  *        mailbox name to delete
  542.  * Returns: T on success, NIL on failure
  543.  */
  544.  
  545. long
  546. context_delete (context, stream, name)
  547.     char       *context;
  548.     MAILSTREAM *stream;
  549.     char       *name;
  550. {
  551.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  552.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  553.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  554.       strncpy(tmp, context, (s - context) + 1);
  555.       strcpy(&tmp[(s - context)+1], name);
  556.       s = tmp;
  557.   }
  558.   else s = name;        /* fully-qualified name */
  559.   return(cntxt_allowed(s) ? mail_delete(stream,s) : 0L);
  560. }
  561.  
  562.  
  563. /* Context Manager append message string
  564.  * Accepts: context
  565.  *        mail stream
  566.  *        destination mailbox
  567.  *        stringstruct of message to append
  568.  * Returns: T on success, NIL on failure
  569.  */
  570.  
  571. long
  572. context_append (context, stream, name, msg)
  573.     char       *context;
  574.     MAILSTREAM *stream;
  575.     char       *name;
  576.     STRING     *msg;
  577. {
  578.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  579.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  580.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  581.       strncpy(tmp, context, (s - context) + 1);
  582.       strcpy(&tmp[(s - context)+1], name);
  583.       s = tmp;
  584.   }
  585.   else s = name;        /* fully-qualified name */
  586.   return(cntxt_allowed(s) ? mail_append(stream,s,msg) : 0L);
  587. }
  588.  
  589.  
  590. /* Context Manager append message string with flags
  591.  * Accepts: context
  592.  *        mail stream
  593.  *        destination mailbox
  594.  *          flags to assign message being appended
  595.  *          date of message being appended
  596.  *        stringstruct of message to append
  597.  * Returns: T on success, NIL on failure
  598.  */
  599.  
  600. long context_append_full (context, stream, name, flags, date, msg)
  601.     char       *context;
  602.     MAILSTREAM *stream;
  603.     char       *name, *flags, *date;
  604.     STRING     *msg;
  605. {
  606.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  607.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  608.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  609.       strncpy(tmp, context, (s - context) + 1);
  610.       strcpy(&tmp[(s - context)+1], name);
  611.       s = tmp;
  612.   }
  613.   else s = name;        /* fully-qualified name */
  614.   return(cntxt_allowed(s) ? mail_append_full(stream,s,flags,date,msg) : 0L);
  615. }
  616.  
  617.  
  618. /* Mail copy message(s)
  619.  * Accepts: context
  620.  *        mail stream
  621.  *        sequence
  622.  *        destination mailbox
  623.  */
  624.  
  625. long context_copy (context, stream, sequence, name)
  626.     char *context;
  627.     MAILSTREAM *stream;
  628.     char *sequence;
  629.     char *name;
  630. {
  631.   char *s,tmp[MAILTMPLEN];        /* build FQN from ambiguous name */
  632.   if (context_isambig (name)) context_apply (tmp,context,name);
  633.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  634.       strncpy(tmp, context, (s - context) + 1);
  635.       strcpy(&tmp[(s - context)+1], name);
  636.   }
  637.   else strcpy(tmp,name);        /* fully-qualified name */
  638.   if((*(s=tmp) == '{' || (*s == '*' && *(s+1) == '{')) && (s=strindex(s,'}'))){
  639.       if(!*++s)                /* strip imap host name ? */
  640.     strcpy(s = tmp, "INBOX");    /* presume "inbox" ala c-client */
  641.   }
  642.  
  643.   return((s && cntxt_allowed(s)) ? mail_copy(stream,sequence,s) : 0L);
  644. }
  645.  
  646.  
  647. /* Context Manager subscribe
  648.  * Accepts: context
  649.  *        mail stream
  650.  *        mailbox name to delete
  651.  * Returns: T on success, NIL on failure
  652.  */
  653.  
  654. long
  655. context_subscribe (context, stream, name)
  656.     char       *context;
  657.     MAILSTREAM *stream;
  658.     char       *name;
  659. {
  660.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  661.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  662.   else s = name;        /* fully-qualified name */
  663.   return mail_subscribe (stream,s);
  664. }
  665.  
  666.  
  667. /* Context Manager unsubscribe
  668.  * Accepts: context
  669.  *        mail stream
  670.  *        mailbox name to delete
  671.  * Returns: T on success, NIL on failure
  672.  */
  673.  
  674. long
  675. context_unsubscribe (context, stream, name)
  676.     char       *context;
  677.     MAILSTREAM *stream;
  678.     char       *name;
  679. {
  680.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  681.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  682.   else s = name;        /* fully-qualified name */
  683.   return mail_unsubscribe (stream,s);
  684. }
  685.  
  686.  
  687. /*
  688.  * Context manager stream usefulness test
  689.  * Accepts: context
  690.  *        mail name
  691.  *        mailbox name
  692.  *        mail stream to test against mailbox name
  693.  * Returns: stream if useful, else NIL
  694.  */
  695. MAILSTREAM *
  696. context_same_stream(context, name, stream)
  697.     char       *context;
  698.     MAILSTREAM *stream;
  699.     char       *name;
  700. {
  701.   extern MAILSTREAM *same_stream();
  702.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  703.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  704.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  705.       strncpy(tmp, context, (s - context) + 1);
  706.       strcpy(&tmp[(s - context)+1], name);
  707.       s = tmp;
  708.   }
  709.   else s = name;        /* fully-qualified name */
  710.   return same_stream (s,stream);
  711. }
  712.  
  713.  
  714. /*
  715.  * Context manager driver compatibility test
  716.  * Accepts: context
  717.  *        mail name
  718.  *        mailbox name
  719.  *        mail stream to test against mailbox name
  720.  * Returns: stream if drivers are the same, else NIL
  721.  */
  722. MAILSTREAM *
  723. context_same_driver(context, name, stream)
  724.     char       *context;
  725.     MAILSTREAM *stream;
  726.     char       *name;
  727. {
  728.   MAILSTREAM *proto_stream;
  729.   int rv;
  730.   char *s,tmp[MAILTMPLEN];    /* build FQN from ambiguous name */
  731.   if (context_isambig (name)) context_apply (s = tmp,context,name);
  732.   else if(name[0] != '{' && context[0] == '{' && (s = strindex(context, '}'))){
  733.       strncpy(tmp, context, (s - context) + 1);
  734.       strcpy(&tmp[(s - context)+1], name);
  735.       s = tmp;
  736.   }
  737.   else s = name;        /* fully-qualified name */
  738.  
  739.   if(!cntxt_allowed(s))
  740.     return((MAILSTREAM *)NULL);
  741.  
  742.   /* IF we're given a stream to compare *and* it's not remote *and*
  743.    * the given mailbox name isn't remote *and* we know the driver
  744.    * the given mailbox will be in *and* the drivers are the same
  745.    * return the given stream.
  746.    *
  747.    * Also, turn off any mm_log errors that might bubble up from 
  748.    * mail_open because anything other than "doesn't exist" will
  749.    * get encountered during whatever action follows this call...
  750.    */
  751.   ps_global->try_to_create = 1;
  752.   rv = (stream
  753.     && !((*stream->mailbox == '{'
  754.           || (*stream->mailbox == '*' && *(stream->mailbox + 1) == '{'))
  755.          || (*s == '{' || (*s == '*' && *(s+1) == '{')))
  756.     && ((proto_stream = mail_open(NIL,s,OP_PROTOTYPE))
  757.         || (*s != '#' && (proto_stream = default_proto())))
  758.     && !strcmp(stream->dtb->name, proto_stream->dtb->name));
  759.   ps_global->try_to_create = 0;
  760.  
  761.   return(rv ? stream : NULL);
  762. }
  763.  
  764.  
  765. #ifdef NEWBB
  766.  
  767. /*  This is code for inclusion in the c-client to support the command
  768.     to discover all the new newly created news groups, since the last
  769.     time the subscription screen was viewed. 
  770.  
  771.     Some of this code goes un nntpunx.c and one line in nntpunx.h
  772.  
  773.     It's not clear whether or not this code will be included as part
  774.     of the official c-client distribution so it's included here.
  775. */
  776.  
  777. #ifdef INCLUDE_THIS_CODE_AT_THE_END_OF_NNTPUNX_C
  778.  
  779. /* NNTP mail find list of all bboards
  780.  * Accepts: mail stream
  781.  *        pattern to search
  782.  *          last time that new groups were checked for in NNTP format
  783.  */
  784.  
  785. void nntp_find_new_bboard (stream, pat, lasttime)
  786.     MAILSTREAM *stream;
  787.     char       *pat, *lasttime;
  788. {
  789.   char *s,*t,*bbd,*patx,tmp[MAILTMPLEN], checktime[20];
  790.                 /* use .newsrc if a stream given */
  791.   if (stream && LOCAL && LOCAL->nntpstream) {
  792.                 /* begin with a host specification? */
  793.     if (((*pat == '{') || ((*pat == '*') && (pat[1] == '{'))) &&
  794.     (t = strchr (pat,'}')) && *(patx = ++t)) {
  795.       if (*pat == '*') pat++;    /* yes, skip leading * (old Pine behavior) */
  796.       strcpy (tmp,pat);        /* copy host name */
  797.       bbd = tmp + (patx - pat);    /* where we write the bboards */
  798.     }
  799.     else {            /* no host specification */
  800.       bbd = tmp;        /* no prefix */
  801.       patx = pat;        /* use entire specification */
  802.     }
  803.                 /* ask server for all active newsgroups */
  804.     if (!(smtp_send (LOCAL->nntpstream,"NEWGROUPS",lasttime) == NNTPNEWLIST))
  805.       return;
  806.                 /* process data until we see final dot */
  807.     while ((s = tcp_getline (LOCAL->nntpstream->tcpstream)) && *s != '.') {
  808.                 /* tie off after newsgroup name */
  809.       if (t = strchr (s,' ')) *t = '\0';
  810.       if (pmatch (s,patx)) {    /* report to main program if have match */
  811.     strcpy (bbd,s);        /* write newsgroup name after prefix */
  812.     mm_bboard(tmp);
  813.       }
  814.       fs_give ((void **) &s);    /* clean up */
  815.     }
  816.   }
  817. }
  818.  
  819.      
  820. #endif
  821.  
  822.  
  823. #ifdef INCLUDE_THIS_CODE_NEAR_THE_TOP_OF_NNTPUNX_H
  824.  
  825. #define NNTPNEWLIST (long) 231  /* NNTP list of new news groups */
  826.  
  827. #endif
  828.  
  829. #endif /* NEWBB */
  830.